#include "DelayQueue.h"
#include "utils/utils.h"

namespace zeroplus::mq
{
    DelayQueue::DelayQueue(std::shared_ptr<sw::redis::Redis> redisFd)
        : redis_(redisFd)
    {
    }

    DelayQueue::~DelayQueue()
    {
    }

    // 启动延迟队列
    void DelayQueue::Start()
    {
        if (!onTaskExecute_)
        {
            LOG_FATAL("onTaskExecute callback is not registered");
        }
        loop_.set_name("DelayQueue");
        loop_.async_run();
        searchDelayTaskTimer_ = std::make_shared<Timer>(&loop_,
                                                        NetworkFrequency::delayTaskSearchFrequency,
                                                        Timer::kInfinite,
                                                        std::bind(&DelayQueue::SearchDelayTask, this));
        searchDelayTaskTimer_->start();
    }

    // 停止延迟队列
    void DelayQueue::Stop()
    {
        searchDelayTaskTimer_->stop();
        loop_.quit();
        loop_.wait_for_quit();
    }

    // 获取分钟级时间片键
    std::string DelayQueue::GetMinuteSliceKey(uint64_t timestamp)
    {
        uint64_t minuteTimestamp = (timestamp / 60000) * 60000; // 按分钟对齐
        return "delayQueue:" + std::to_string(minuteTimestamp);
    }

    // 写入任务到 Redis
    bool DelayQueue::WriteToStorage(const std::string &key, const uint64_t &delay, const Bytes &message)
    {
        DelayTaskInfo delayTaskInfo;
        delayTaskInfo.topic = key;
        delayTaskInfo.message = message.to_string();
        uint64_t currentTime = Utils::GetCurrentTimeMillis();
        uint64_t executeTime = currentTime + delay;
        // 获取分钟级时间片键
        std::string sliceKey = GetMinuteSliceKey(executeTime);
        // 将任务写入对应的 ZSET
        std::vector<std::pair<std::string, double>> elements = {{DelayTaskCodec::Encode(delayTaskInfo).to_string(), executeTime}};
        redis_->zadd(sliceKey, elements.begin(), elements.end(), sw::redis::UpdateType::ALWAYS, true);
        return true;
    }

    // 标记任务为已删除
    void DelayQueue::MarkTaskAsDeleted(const std::string &task)
    {
        redis_->sadd("delayQueue:deletedTasks", task); // 使用Redis SET记录
    }

    // 检查任务是否已删除
    bool DelayQueue::IsTaskDeleted(const std::string &task)
    {
        return redis_->sismember("delayQueue:deletedTasks", task);
    }

    void DelayQueue::SearchDelayTask()
    {
        LOG_DEBUG("定期轮询");
        uint64_t currentTime = Utils::GetCurrentTimeMillis();

        // 遍历所有时间片
        std::string sliceKey = GetMinuteSliceKey(currentTime);

        // 查询当前时间片内的任务(-inf, currentTime]
        std::vector<std::string> result;
        redis_->zrangebyscore(sliceKey,
                              sw::redis::LeftBoundedInterval<double>(currentTime, sw::redis::BoundType::RIGHT_OPEN),
                              std::back_inserter(result));

        // 处理任务
        for (const auto &task : result)
        {
            if (!IsTaskDeleted(task))
            {
                // LOG_DEBUG("ExecuteTask: %s", task.c_str());
                bool res = onTaskExecute_(task);
                if (res)
                {
                    MarkTaskAsDeleted(task);
                }
            }
        }

        // 删除已处理的任务
        // redis_->zremrangebyscore(sliceKey,
        //                         sw::redis::LeftBoundedInterval<double>(0, sw::redis::BoundType::RIGHT_OPEN));
        // long long removedCnt = redis_->zrem(key, result.begin(), result.end());
    }

}
